/*
 * Copyright (c) 2009 Nathaniel Houghton <nathan@brainwerk.org>
 *                    Robert Kirchgessner <rkirchge@gmail.com>
 *
 * Permission to use, copy, modify, and distribute this software for
 * any purpose with or without fee is hereby granted, provided that
 * the above copyright notice and this permission notice appear in all
 * copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/crc16.h>

#include "../usart.h"
#include "../lcd.h"
#include "../util.h"
#include "../spi.h"
#include "../nvm.h"
#include "../config.h"
#include "../event.h"
#include "../ui.h"

#include "../mode.h"
#include "../elm.h"

/* global variables */
struct config cfg;
struct lcd lcd;

int
main(int argc, char **argv)
{
	char buf[32];
	struct mode mode;

	lcd_init();
	usart_init();
	spi_init();
	nvm_unlock();
	init_ui();

	if (read_config(&cfg) == -1) { /*Reads the config, and writes default if not valid*/
		memset(&cfg, 0, sizeof(cfg));
		write_config(&cfg);
	}

	event_init(&cfg.event[0]);

	memset(&mode, 0, sizeof(mode));
	mode.mode = MODE_CONFIG;
	mode.state = STATE_0_INIT;

	sei();

	/* Wait for ELM to start up. */
	elm_pwrwait();

	if (btn_down(BTN_LCDPRESENT))
		lcd.initd = 1;

	for (;;) {
		mode_seq(&mode);
		if (mode.mode == MODE_ELM)
			elm_mode(&mode);
		else if (mode.mode == MODE_CONFIG)
			config_mode(&mode);
		else if (mode.mode == MODE_LOG)
			log_mode(&mode);

		if (btn_down(BTN_LCDPRESENT)) {
			if (!lcd.initd) {
				lcd_init();
				lcd.initd = 1;
				snprintf(buf, sizeof(buf), "Mode: %s",
				    mode_str[mode.mode]);
				lcd_update(&lcd, 0, buf);
			}
		} else
			lcd.initd = 0;
	}

	return 0;
}
